/**************************************************************************************************
* Filename:			CTimer.h
* Date:				05/09/10
* Mod. Date:		05/16/10
* Mod. Initials:	MG
* Author:			Malcolm J. Gruber
* Purpose:			A Timer system for getting time, and alarm and stop watch functionality.
**************************************************************************************************/

#ifndef _CTIMER_H_
#define _CTIMER_H_

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "DList.h"

typedef unsigned long DWORD;

class CTimer
{
private:
	class CAlarm
	{
	private:
		friend CTimer;
		CTimer* m_pOwner;
		bool	m_szRunning;
		float	m_fTime;
		DWORD	m_dwCurrentTime;
		void	(*m_fpToExecute)(void);

	public:
		/*************************************************************************
		* CAlarm():						Constructor for CAlarm
		*
		* Ins:							CTimer* pOwner
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		CAlarm(CTimer* pOwner);
		/*************************************************************************
		* ~CAlarm():					Destructor for CAlarm
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		~CAlarm(void);
		/*************************************************************************
		* Start():						Starts the alarm for the given amount 
		*								of time and executes the given function
		*								if there is one.
		*
		* Ins:							float amount
		*								void (*functionToExecute)(void)
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Start(float amount, void(*functionToExecute)(void) = NULL);
		/*************************************************************************
		* Update():						Updates the state of the alarm.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Update(void);
		/*************************************************************************
		* Stop():						Stops the alarm and clears some info.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Stop(void);
		/*************************************************************************
		* Check():						Checks how much time is left and returns
		*								it.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						float
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		float Check(void);
	};

	class CStopWatch
	{
	private:
		friend CTimer;
		CTimer* m_pOwner;
		bool	m_szRunning;
		float	m_fTime,
				m_fFrequency;
		DWORD	m_dwStartTime,
				m_dwCurrentTime;
		void	(*m_fpToExecute)(void);

	public:
		/*************************************************************************
		* CStopWatch():					Constructor for CStopWatch
		*
		* Ins:							CTimer* pOwner
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		CStopWatch(CTimer* pOwner);
		/*************************************************************************
		* ~CStopWatch():				Destructor for CStopWatch
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		~CStopWatch(void);
		/*************************************************************************
		* Start():						Starts the stop watch, given a frequency
		*								to execute the given function if there is 
		*								one. Frequency can be set to 0 or less to
		*								not execute at all.
		*
		* Ins:							float frequency
		*								void (*functionToExecute)(void)
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/10/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Start(float frequency = 0.0f, void(*functionToExecute)(void) = NULL);
		/*************************************************************************
		* Continue():					Starts the watch up again the at the 
		*								given time.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Continue(void);
		/*************************************************************************
		* Update():						Updates the stop watch.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						void
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		void Update(void);
		/*************************************************************************
		* Stop():						Stops the stop watch, and returns the 
		*								time that it's been running for.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						float
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		float Stop(void);
		/*************************************************************************
		* GetTimeCount():				Gets and returns the amount of time the 
		*								stop watch has been running for.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						float
		*
		* Mod. Date:					05/10/10
		* Mod. Initials:				MG
		*************************************************************************/
		float GetTimeCount(void);
		/*************************************************************************
		* IsRunning():					Returns whether or not the stop watch is 
		*								running.
		*
		* Ins:							void
		*
		* Outs:							void
		*
		* Returns:						bool
		*
		* Mod. Date:					05/09/10
		* Mod. Initials:				MG
		*************************************************************************/
		bool IsRunning(void);
		void SetRunning( bool bRunning ) { m_szRunning = bRunning; }
	};

	DWORD	m_dwStartTime,
			m_dwCurrentTime,
			m_dwPrevTime;
	float	m_fDTime,
			m_fTotTime;

	static CTimer	m_siInstance;

	DList<CAlarm*>		m_cAlarms;
	DList<CStopWatch*>	m_cStopWatches;

	/*************************************************************************
	* UpdateWatches():				Updates all of the watches.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void UpdateWatches(void);
	/*************************************************************************
	* ClearWatches():				Clears all of the watches.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void ClearWatches(void);
	/*************************************************************************
	* UpdateAlarms():				Updates all of the alarms.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void UpdateAlarms(void);
	/*************************************************************************
	* ClearAlarms():				Clears all of the alarms.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void ClearAlarms(void);

	/*************************************************************************
	* CTimer():						Constructor for CTimer
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	CTimer(void);
	CTimer(const CTimer& timer);
	CTimer* operator=(const CTimer& timer);
	/*************************************************************************
	* ~CTimer():					Destructor for CTimer
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	~CTimer(void);

public:
	/*************************************************************************
	* GetInstance():				Returns an instance to the timer class.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						CTimer*
	*
	* Mod. Date:					05/16/10
	* Mod. Initials:				MG
	*************************************************************************/
	static CTimer* GetInstance(void);
	
	/*************************************************************************
	* InitalizeTimer():				Initalizes the timer.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void InitalizeTimer(void);
	/*************************************************************************
	* Update():						Updates the timer.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void Update(void);
	/*************************************************************************
	* Reset():						Resets the timer.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void Reset(void);
	/*************************************************************************
	* ShutdownTimer():				Shuts down the timer.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void ShutdownTimer(void);

	/*************************************************************************
	* GetElapsedTime():				Returns the change in time from the last
	*								update call.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	float GetElapsedTime(void);
	/*************************************************************************
	* GetTotalTime():				Returns the amount of time that has 
	*								passed since initalization or a reset.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	float GetTotalTime(void);

	/*************************************************************************
	* CreateAlarm():				Creates an alarm and returns and ID to it.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						unsigned int
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	unsigned int CreateAlarm(void);
	/*************************************************************************
	* StartAlarm():					Starts the alarm with the given ID,
	*								amount of time to run, and the function 
	*								to execute.
	*
	* Ins:							unsigned int id
	*								float amount
	*								void (*functionToExecute)(void)
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void StartAlarm(unsigned int id, float amount, void(*functionToExecute)(void) = NULL);
	/*************************************************************************
	* RemoveAlarm():				Removes the alarm with the given ID.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	void RemoveAlarm(unsigned int id);
	/*************************************************************************
	* CheckAlarm():					Returns the amount of time left for the
	*								alarm with the given ID.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/09/10
	* Mod. Initials:				MG
	*************************************************************************/
	float CheckAlarm(unsigned int id);

	/*************************************************************************
	* CreateWatch():				Creates an watch and returns and ID to it.
	*
	* Ins:							void
	*
	* Outs:							void
	*
	* Returns:						unsigned int
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	unsigned int CreateWatch(void);
	/*************************************************************************
	* StartWatch():					Creates the alarm with the given ID,
	*								amount of time between function 
	*								executions, and the function to execute.
	*
	* Ins:							unsigned int id
	*								float frequency
	*								void (*functionToExecute)(void)
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void StartWatch(unsigned int id, float frequency, void(*functionToExecute)(void) = NULL);
	/*************************************************************************
	* ContinueWatch():				Continues the stop watch with the 
	*								given ID.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void ContinueWatch(unsigned int id);
	/*************************************************************************
	* StopWatch():					Stops the stop watch with the given ID and 
	*								returns the amount of time the stop watch 
	*								has been running for.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	float StopWatch(unsigned int id);
	/*************************************************************************
	* RemoveWatch():				Removes the watch with the given ID.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						void
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	void RemoveWatch(unsigned int id);
	/*************************************************************************
	* GetWatchTime():				Returns the amount of time the stop watch
	*								with the given ID, has been running for.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	float GetWatchTime(unsigned int id);
	/*************************************************************************
	* IsWatchRunning():				Returns if the stop watch with the given 
	*								ID is running.
	*
	* Ins:							unsigned int id
	*
	* Outs:							void
	*
	* Returns:						float
	*
	* Mod. Date:					05/10/10
	* Mod. Initials:				MG
	*************************************************************************/
	bool IsWatchRunning(unsigned int id);
	void SetWatchingRunningState( unsigned int id, bool bRunning ){ m_cStopWatches[id]->SetRunning(bRunning); }

};

#endif // _CTIMER_H_